package br.ufpe.cin.msc.jrsj2.recommender.persistence.dao.jpa;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;

import br.ufpe.cin.msc.jrsj2.recommender.persistence.dao.ClientDAO;
import br.ufpe.cin.msc.jrsj2.recommender.persistence.dao.DAOFactory;
import br.ufpe.cin.msc.jrsj2.recommender.persistence.dao.ProfileDAO;
import br.ufpe.cin.msc.jrsj2.recommender.persistence.dao.ProgramDAO;
import br.ufpe.cin.msc.jrsj2.recommender.persistence.domain.Client;
import br.ufpe.cin.msc.jrsj2.recommender.persistence.domain.Profile;
import br.ufpe.cin.msc.jrsj2.recommender.persistence.domain.Program;

public class JPAProfileDAO implements ProfileDAO {

	private EntityManager emf;

	public JPAProfileDAO(EntityManager emf) {
		this.emf = emf;
	}

	@Override
	public Profile create(Profile profile) {
		if (profile.getId() == null) {
			Program program = profile.getProgram();
			Client client = profile.getClient();

			if (profile.getProgram().getId() == null) {
				ProgramDAO programDAO = DAOFactory.getDAOFactory()
						.getProgramDAO();
				program = programDAO.findByTitle(profile.getProgram()
						.getTitle());
			}
			if (profile.getClient().getId() == null) {
				ClientDAO clientDAO = DAOFactory.getDAOFactory().getClientDAO();

				client = clientDAO.findByHash(profile.getClient().getHash());
			}

			profile = new Profile(program, client, profile.getRating());
		}

		try {
			emf.getTransaction().begin();
			emf.persist(profile);
			emf.getTransaction().commit();
			return profile;
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Profile> findProfileByClient(Client client) {
		try {
			List<Profile> result = emf
					.createQuery(
							"SELECT p FROM Profile p WHERE p.clientId = :clientId")
					.setParameter("clientId", client.getId()).getResultList();
			List<Profile> profiles = new ArrayList<Profile>();
			ProgramDAO programDAO = DAOFactory.getDAOFactory().getProgramDAO();
			ClientDAO clientDAO = DAOFactory.getDAOFactory().getClientDAO();

			for (Profile profile : result) {
				Program _program = programDAO.get(profile.getProgramId());
				Client _client = clientDAO.get(profile.getClientId());
				profile.setProgram(_program);
				profile.setClient(_client);
				profiles.add(profile);
			}

			return profiles;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Profile> findProfileByProgram(Program program) {
		try {
			List<Profile> result = emf
					.createQuery(
							"SELECT p FROM Profile p WHERE p.programId = :programId")
					.setParameter("programId", program.getId()).getResultList();
			List<Profile> profiles = new ArrayList<Profile>();
			ProgramDAO programDAO = DAOFactory.getDAOFactory().getProgramDAO();
			ClientDAO clientDAO = DAOFactory.getDAOFactory().getClientDAO();

			for (Profile profile : result) {
				Program _program = programDAO.get(profile.getProgramId());
				Client _client = clientDAO.get(profile.getClientId());
				profile.setProgram(_program);
				profile.setClient(_client);
				profiles.add(profile);
			}

			return profiles;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Profile> loadAll() {
		try {
			List<Profile> result = emf.createQuery("SELECT p FROM Profile p")
					.getResultList();
			List<Profile> profiles = new ArrayList<Profile>();
			ProgramDAO programDAO = DAOFactory.getDAOFactory().getProgramDAO();
			ClientDAO clientDAO = DAOFactory.getDAOFactory().getClientDAO();

			for (Profile profile : result) {
				Program _program = programDAO.get(profile.getProgramId());
				Client _client = clientDAO.get(profile.getClientId());
				profile.setProgram(_program);
				profile.setClient(_client);
				profiles.add(profile);
			}

			return profiles;
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}

	@Override
	public List<Profile> loadAllUnless(Client client) {
		try {
			List<Profile> result = loadAll();
			List<Profile> profiles = new ArrayList<Profile>();

			for (Profile profile : result)
				if (!profile.getClient().getHash().equals(client.getHash()))
					profiles.add(profile);

			return profiles;
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}

	@Override
	public int countRating(Program program) {
		try {
			return (Integer) emf
					.createQuery(
							"SELECT COUNT(p) FROM Profile p WHERE p.programId = :programId")
					.setParameter("programId", program.getId())
					.getSingleResult();
		} catch (Exception ex) {
			ex.printStackTrace();
			return -1;
		}
	}

	@Override
	public void remove(Profile profile) {
		// TODO Auto-generated method stub

	}

}
